﻿namespace FitnessTracker.Packet
{
    using System;
    using FitnessTracker.Entities;
    using FitnessTracker.HxM;

    public static class HxMPacketStructureValidator
    {
        private static readonly FitnessTrackerEntities FitnessTrackerEntities = new FitnessTrackerEntities();
        
        public static bool IsStructureValid(byte[] bufferData)
        {
            return     IsPacketLengthValid(bufferData)
                    && IsSTXMarkerPresent(bufferData)
                    && IsMessageIDPresent(bufferData)
                    && IsDLCMarkerPresent(bufferData)
                    && IsETXMarkerPresent(bufferData);
        }

        private static bool IsETXMarkerPresent(byte[] bufferData)
        {
            if (bufferData[HxMPacketStructure.ETXPositionOffset] != HxMPacketMarkers.ETX)
            {
                var faultDescription = "Invalid ETX was received. Actual Value was " +
                                        bufferData[HxMPacketStructure.ETXPositionOffset] + "." +
                                        "Expected value was " + HxMPacketMarkers.ETX;
                LogFaultyPacket(bufferData, faultDescription);
                return false;
            }

            return true;
        }

        private static bool IsDLCMarkerPresent(byte[] bufferData)
        {
            if (bufferData[HxMPacketStructure.DLCLocationOffset] != HxMPacketMarkers.DLC)
            {
                var faultDescription = "Invalid DLC was received. Actual Value was " +
                                        bufferData[HxMPacketStructure.DLCLocationOffset] + "." +
                                        "Expected value was " + HxMPacketMarkers.DLC;
                LogFaultyPacket(bufferData, faultDescription);
                return false;
            }

            return true;
        }

        private static bool IsMessageIDPresent(byte[] bufferData)
        {
            if (bufferData[HxMPacketStructure.MessageIDLocationOffset] != HxMPacketMarkers.MessageID)
            {
                var faultDescription = "Invalid MessageID was received. Actual Value was " +
                                        bufferData[HxMPacketStructure.MessageIDLocationOffset] + "." +
                                        "Expected value was " + HxMPacketMarkers.MessageID;
                LogFaultyPacket(bufferData, faultDescription);
                return false;
            }

            return true;
        }

        private static bool IsSTXMarkerPresent(byte[] bufferData)
        {
            if (bufferData[HxMPacketStructure.STXPositionOffset] != HxMPacketMarkers.STX)
            {
                var faultDescription = "Invalid Start of Packet Value received. Actual Value was " + 
                                        bufferData[HxMPacketStructure.STXPositionOffset] + "." + 
                                        "Expected value was " + HxMPacketMarkers.STX;
                
                LogFaultyPacket(bufferData, faultDescription);
                return false;
            }

            return true;
        }

        private static bool IsPacketLengthValid(byte[] bufferData)
        {
            if (bufferData.Length != HxMPacketMarkers.PacketSize)
            {
                var faultDescription = "Packet was received with invalid length. Actual length was " + bufferData.Length
                                       + " expected length was " + HxMPacketMarkers.PacketSize;
                LogFaultyPacket(bufferData, faultDescription);
                return false;
            }

            return true;
        }

        private static void LogFaultyPacket(byte[] bufferData, string faultDescription)
        {
            var packetFaultsLog = new PacketFaultsLog
            {
                timeStamp = DateTime.Now,
                description = faultDescription,
                packet = bufferData
            };
            FitnessTrackerEntities.PacketFaultsLogs.Add(packetFaultsLog);
            FitnessTrackerEntities.SaveChanges();
        }
    }
}
